/*
 * Copyright 2012 Netflix, Inc.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.netflix.eureka.util;

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Utility class for getting a count in last X milliseconds.
 *
 * @author Karthik Ranganathan,Greg Kim
 */
public class MeasuredRate {
    private static final Logger logger = LoggerFactory.getLogger(MeasuredRate.class);

    //保存的是，上一次，一分钟，累计的心跳数量。
    private final AtomicLong lastBucket = new AtomicLong(0);

    // 当前一分钟里的心跳次数。
    private final AtomicLong currentBucket = new AtomicLong(0);

    /**
     *  默认：1000 * 60 * 1  = 1分钟
     */
    private final long sampleInterval;
    private final Timer timer;

    private volatile boolean isActive;

    /**
     * @param sampleInterval in milliseconds
     */
    public MeasuredRate(long sampleInterval) {
        this.sampleInterval = sampleInterval;
        this.timer = new Timer("Eureka-MeasureRateTimer", true);
        this.isActive = false;
    }


    /**
     *  每1分钟会执行这个任务
     */
    public synchronized void start() {
        if (!isActive) {
            timer.schedule(new TimerTask() {

                @Override
                public void run() {
                    try {
                        /**
                         *  定时任务1分钟执行一次。
                         *  假如：一分钟里，currentBucket 累计到了88
                         *  1、于是就将currentBucket =88 的值，设置到lastBucket 里。
                         *  2、将currentBucket的值设为0。重新开始记录下一分钟的心跳数量。
                         *  ====================================================
                         *  lastBucket ： 保留了上一分钟，心跳的数量
                         *  currentBucket ： 当前一分钟里，心跳的数量。
                         */
                        lastBucket.set(currentBucket.getAndSet(0));
                    }
                    catch (Throwable e) {
                        logger.error("Cannot reset the Measured Rate", e);
                    }
                }
            }, sampleInterval, sampleInterval);

            isActive = true;
        }
    }

    public synchronized void stop() {
        if (isActive) {
            timer.cancel();
            isActive = false;
        }
    }

    /**
     * Returns the count in the last sample interval.
     */
    public long getCount() {
        return lastBucket.get();
    }

    /**
     *  每接收一次心跳，就加1
     */
    public void increment() {
        //  比如说一开始，currentBucket=1 、、、、、、currentBucket=88
        currentBucket.incrementAndGet();
    }
}
